#include <iostream>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <cstring>
#include <json-c/json.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>

#define SERVER_PORT 9090
#define FILE_SIZE 64
#define BUFFER_SIZE 2048

struct FileClass
{
    char name[FILE_SIZE];
    size_t size;
};

struct DataClass
{
    int num;
    char data[BUFFER_SIZE];
};

typedef struct FileClass FileClass;
typedef struct DataClass DataClass;

int main(int argc, char const *argv[])
{
    // 创建socket句柄
    int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
    if (sockfd == -1)
    {
        perror("socket error.");
        exit(-1);
    }

    //  设置地址复用
    int optVal = 1;
    int ret = setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &optVal, sizeof(optVal));
    if (ret == -1)
    {
        perror("setsockopt error");
        _exit(-1);
    }

    /*绑定服务器的ip和端口信息*/
    sockaddr_in localAddress;
    /*清除脏数据*/
    memset(&localAddress, 0, sizeof(localAddress));
    /*地址族*/
    localAddress.sin_family = AF_INET; // ipv4
    /* 端口 */
    localAddress.sin_port = htons(SERVER_PORT); // 大小端转换
    localAddress.sin_addr.s_addr = INADDR_ANY;  // 允许接收来自任意IP地址的连接

    ret = bind(sockfd, (const sockaddr *)&localAddress, sizeof(localAddress));
    if (ret == -1)
    {
        perror("bind error:");
        _exit(-1);
    }
    char buffer[BUFFER_SIZE] = {0};

    FileClass information;
    DataClass datainfo;
    memset(&information, 0, sizeof(information));
    memset(&datainfo, 0, sizeof(datainfo));

    recvfrom(sockfd, &information, sizeof(FileClass), 0, NULL, NULL);
    information.name[FILE_SIZE - 1] = '\0'; // 确保字符串以'\0'结尾
    printf("name:%s\tsize:%ld\n", information.name, information.size);
    int fd = open(information.name, O_WRONLY | O_CREAT, 0644);
    ret = ftruncate(fd, information.size);

    // 接收端代码修改
    while (1)
    {
        ssize_t size = recvfrom(sockfd, &datainfo, sizeof(DataClass), 0, NULL, NULL);
        if (size < 0)
        {
            perror("recvfrom error");
            exit(-1);
        }

        if (datainfo.num == -1)
        {
            printf("文件上传完成\n");
            break;
        }

        ssize_t data_size = size - sizeof(datainfo.num);
        lseek(fd, ((datainfo.num - 1) * BUFFER_SIZE), SEEK_SET);
        write(fd, datainfo.data, data_size);
        memset(datainfo.data, 0, sizeof(datainfo.data));
    }
    close(fd);
    close(sockfd);

    return 0;
}